package com.github.springbootPlus.excel.util;


import sun.misc.BASE64Decoder;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.BreakIterator;
import java.util.*;

/**
 * @author
 * @version V1.0
 * @ClassName StringUtil
 * @Description 字符串工具类
 * @date 2017年9月19日 上午11:43:41
 * @since V1.0
 */
public class StringUtils extends org.springframework.util.StringUtils {

    /**
     * 判断字符串是否为空
     *
     * @param s
     * @return 是否为空
     */
    public static boolean isNullStr(String s) {
        if (s == null || s.trim().length() <= 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 将Object对象转变为String类型对象，对于null值返回空字符串.
     *
     * @param inObj 待处理的对象.
     */
    public static String killNull(Object inObj) {
        if (inObj == null) {
            return "";
        }
        return inObj.toString().trim();
    }

    /**
     * 将Object对象转变为String类型对象，对于null值返回缺省字符串.
     *
     * @param inObj 待处理的对象.
     */
    public static String killNull(Object inObj, String toStr) {
        if (inObj == null) {
            return toStr;
        }
        return inObj.toString().trim();
    }

    /**
     * 替换source中的str1为str2
     *
     * @param source
     * @param str1
     * @param str2
     * @return
     */
    public static String replace(String source, char str1, String str2) {
        if (source == null) {
            return source;
        }
        String desc = "";
        for (int i = 0; i < source.length(); i++) {
            if (source.charAt(i) == str1) {
                desc = desc + str2;
            } else {
                desc = desc + String.valueOf(source.charAt(i));
            }
        }
        return desc;
    }

    /**
     * 替换source中的str1为str2
     *
     * @param source
     * @param str1
     * @param str2
     * @return
     */
    public static String replace(String source, String str1, String str2) {
        if (source == null) {
            return source;
        }
        String desc = "";
        int i = 0;
        while (i < source.length()) {
            if (source.startsWith(str1, i)) {
                desc = desc + str2;
                i = i + str1.length();
            } else {
                desc = desc + String.valueOf(source.charAt(i));
                i++;
            }

        }
        return desc;
    }

    /**
     * 对字符串表示的数字，按照指定的小数点位数四舍五入。
     *
     * @param numberStr
     * @param decimalIndex 小数点后第几位
     * @return
     */
    public static String round(String numberStr, int decimalIndex) {
        //判断是否为数字。

        //截取字符串
        String desStr = numberStr.substring(0, (numberStr.lastIndexOf(".") + 1) + (decimalIndex + 1));
        //四舍五入
        BigDecimal deSource = new BigDecimal(desStr);
        String newStr = String.valueOf(deSource.setScale(decimalIndex, BigDecimal.ROUND_HALF_UP).doubleValue());

        return new String(newStr);
    }

    /**
     * 将List 中的String对象连接成一个字符串，以指定的字符串分隔
     *
     * @param list
     * @param link
     * @return
     */
    public static String listToString(List<String> list, String link) {
        StringBuffer sb = new StringBuffer();
        for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
            sb.append(iterator.next()).append(link);
        }
        String rt = sb.toString();
        if (rt.length() > link.length()) {
            rt = rt.substring(0, rt.length() - link.length());
        }
        return rt;
    }


    public static final String[] toLowerCaseWordArray(String text) {
        if (text == null || text.length() == 0)
            return new String[0];
        ArrayList<String> wordList = new ArrayList<String>();
        BreakIterator boundary = BreakIterator.getWordInstance();
        boundary.setText(text);
        int start = 0;
        for (int end = boundary.next(); end != -1; end = boundary.next()) {
            String tmp = text.substring(start, end).trim();
            tmp = replace(tmp, "+", "");
            tmp = replace(tmp, "/", "");
            tmp = replace(tmp, "\\", "");
            tmp = replace(tmp, "#", "");
            tmp = replace(tmp, "*", "");
            tmp = replace(tmp, ")", "");
            tmp = replace(tmp, "(", "");
            tmp = replace(tmp, "&", "");
            if (tmp.length() > 0)
                wordList.add(tmp);
            start = end;
        }

        return (String[]) wordList.toArray(new String[wordList.size()]);
    }


    /**
     * 此方法完成：对一个字符串，按某种分割符，分成字符串数组
     *
     * @param sourceString :源字符串
     * @param strInterval  :间隔
     */
    public static Vector<String> stringToVecor(String sourceString, String strInterval) {
        Vector<String> returnStr = new Vector<String>();
        if (sourceString == "" || strInterval == "") {
            returnStr.addElement(sourceString);
            return returnStr;
        }
        int found_str = sourceString.indexOf(strInterval);
        while (found_str >= 0) {
            returnStr.addElement(sourceString.substring(0, found_str));
            sourceString = sourceString.substring(found_str + strInterval.length());
            found_str = sourceString.indexOf(strInterval);
        }
        if (found_str < 0)
            returnStr.addElement(sourceString);
        return returnStr;
    }


    /**
     * Encode a string using Base64 encoding. Used when storing passwords
     * as cookies.
     * <p/>
     * This is weak encoding in that anyone can use the decodeString
     * routine to reverse the encoding.
     *
     * @param str
     * @return String
     * @deprecated REPLACE Base64Utils
     */
    public static String encodeString(String str) {
        sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
        return new String(encoder.encodeBuffer(str.getBytes())).trim();
    }

    /**
     * Decode a string using Base64 encoding.
     *
     * @param str
     * @return String
     * @deprecated REPLACE Base64Utils
     */
    public static String decodeString(String str) {
        BASE64Decoder dec = new BASE64Decoder();
        try {
            return new String(dec.decodeBuffer(str));
        } catch (IOException io) {
            throw new RuntimeException(io.getMessage(), io.getCause());
        }
    }


    /**
     * 将输入的字符串按照每行显示 width个字符折行。
     *
     * @param input
     * @param width
     * @param locale
     * @return
     */
    public static String wordWrap(String input, int width, Locale locale) {
        if (input == null)
            return "";
        if (width < 5)
            return input;
        if (width >= input.length())
            return input;
        StringBuffer buf = new StringBuffer(input);
        boolean endOfLine = false;
        int lineStart = 0;
        for (int i = 0; i < buf.length(); i++) {
            if (buf.charAt(i) == '\n') {
                lineStart = i + 1;
                endOfLine = true;
            }
            if (i > (lineStart + width) - 1)
                if (!endOfLine) {
                    int limit = i - lineStart - 1;
                    BreakIterator breaks = BreakIterator.getLineInstance(locale);
                    breaks.setText(buf.substring(lineStart, i));
                    int end = breaks.last();
                    if (end == limit + 1 && !Character.isWhitespace(buf.charAt(lineStart + end)))
                        end = breaks.preceding(end - 1);
                    if (end != -1 && end == limit + 1) {
                        buf.replace(lineStart + end, lineStart + end + 1, "\n");
                        lineStart += end;
                    } else if (end != -1 && end != 0) {
                        buf.insert(lineStart + end, '\n');
                        lineStart = lineStart + end + 1;
                    } else {
                        buf.insert(i, '\n');
                        lineStart = i + 1;
                    }
                } else {
                    buf.insert(i, '\n');
                    lineStart = i + 1;
                    endOfLine = false;
                }
        }

        return buf.toString();
    }

    /**
     * 将字符串转为UTF-8 ，用于文件下载时将文件名汉化
     * 注：某些转utf-8可能失效 故加入此转换方式
     *
     * @param string
     * @return
     * @author sql
     */
    public static String toUtf8String(String string) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            char c = string.charAt(i);
            if (c >= 0 && c <= 255) {
                sb.append(c);
            } else {
                byte[] b;
                try {
                    b = Character.toString(c).getBytes("utf-8");

                } catch (Exception ex) {
                    b = new byte[0];
                }
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];
                    if (k < 0)
                        k += 256;
                    sb.append("%" + Integer.toHexString(k).toUpperCase());

                }
            }

        }
        String s_utf8 = sb.toString();
        sb.delete(0, sb.length());
        sb.setLength(0);
        sb = null;
        return s_utf8;
    }


    /**
     * 执行一段javascript脚本并返回结果
     *
     * @param jsString : javascript脚本字符串
     * @param param    : 脚本中使用的变量参数值
     * @return
     * @throws ScriptException
     * @deprecated replace by ScriptEngineUtils.eval
     */
    public static Object evalJSScript(String jsString, Map<String, Object> param) throws ScriptException {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        if (param != null && !param.isEmpty()) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                engine.put(entry.getKey(), entry.getValue());
            }
        }
        Object result = engine.eval(jsString);
        return result;
    }

    /**
     * @return
     * @Description 获取UUID
     * @since V1.0
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * The empty String <code>""</code>.
     *
     * @since 2.0
     */
    public static final String EMPTY = "";

    /**
     * Check whether the given {@code CharSequence} contains actual
     * <em>text</em>.
     * <p>
     * More specifically, this method returns {@code true} if the
     * {@code CharSequence} is not {@code null}, its length is greater than 0,
     * and it contains at least one non-whitespace character.
     * <p>
     *
     * <pre class="code">
     * StringUtils.isBlank(null) = true
     * StringUtils.isBlank("") = true
     * StringUtils.isBlank(" ") = true
     * StringUtils.isBlank("12345") = false
     * StringUtils.isBlank(" 12345 ") = false
     * </pre>
     *
     * @param cs the {@code CharSequence} to check (may be {@code null})
     * @return {@code true} if the {@code CharSequence} is not {@code null}, its
     * length is greater than 0, and it does not contain whitespace only
     * @see Character#isWhitespace
     */
    public static boolean isBlank(final CharSequence cs) {
        return !StringUtils.isNotBlank(cs);
    }

    /**
     * <p>
     * Checks if a CharSequence is not empty (""), not null and not whitespace
     * only.
     * </p>
     *
     * <pre>
     * StringUtils.isNotBlank(null)      = false
     * StringUtils.isNotBlank("")        = false
     * StringUtils.isNotBlank(" ")       = false
     * StringUtils.isNotBlank("bob")     = true
     * StringUtils.isNotBlank("  bob  ") = true
     * </pre>
     *
     * @param cs the CharSequence to check, may be null
     * @return {@code true} if the CharSequence is not empty and not null and
     * not whitespace
     * @see Character#isWhitespace
     */
    public static boolean isNotBlank(final CharSequence cs) {
        return StringUtils.hasText(cs);
    }

    /**
     * Convert a {@code Collection} into a delimited {@code String} (e.g. CSV).
     * <p>
     * Useful for {@code toString()} implementations.
     *
     * @param coll  the {@code Collection} to convert
     * @param delim the delimiter to use (typically a ",")
     * @return the delimited {@code String}
     */
    public static String join(Collection<?> coll, String delim) {
        return StringUtils.collectionToDelimitedString(coll, delim);
    }

    /**
     * Convert a {@code String} array into a delimited {@code String} (e.g.
     * CSV).
     * <p>
     * Useful for {@code toString()} implementations.
     *
     * @param arr   the array to display
     * @param delim the delimiter to use (typically a ",")
     * @return the delimited {@code String}
     */
    public static String join(Object[] arr, String delim) {
        return StringUtils.arrayToDelimitedString(arr, delim);
    }

    /**
     * 生成uuid
     *
     * @return UUID
     */
    public static String getUUId() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 获取固定位数流水号
     *
     * @param seq
     * @param fixNumber
     * @return
     */
    public static String toNumberString(int seq, int fixNumber) {
        String result = seq + "";
        int length = result.length();
        if (length < fixNumber) {
            StringBuffer prefix = new StringBuffer(fixNumber);
            for (int i = 0; i < fixNumber - length; i++)
                prefix.append("0");
            result = prefix + result;
        }
        return result;
    }

    public static String defaultString(String str) {
        return str == null ? EMPTY : str;
    }

    public static String toString(Object obj, String nullStr) {
        return obj == null ? nullStr : obj.toString();
    }

    public static String toString(Object obj) {
        return obj == null ? EMPTY : obj.toString();
    }
}